package com.example.jetpackcomposestate.four

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.FastOutLinearInEasing
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.TweenSpec
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import kotlin.random.Random

/**
 * @author huangzehui
 * @date 3/5/2024 下午10:18 周五
 * @description
 *
 * https://www.bilibili.com/video/BV1ob4y1a7ad/?p=33&spm_id_from=pageDriver&vd_source=e07cc8cc94eb22bd76722071b03cd199
 */

/**
 * https://www.bilibili.com/video/BV1ob4y1a7ad/?p=39&spm_id_from=pageDriver&vd_source=e07cc8cc94eb22bd76722071b03cd199
 *
 * 当TodoItem列表中的条目被选中时，会弹出一个输入框，用于编辑选中TodoItem的信息
 * @param item 选中的TodoItem条目
 * @param onEditItemChange 编辑条目时的回调
 * @param onEditDone 编辑完成时的回调
 * @param onRemoveItem 删除条目时的回调
 */
@Composable
fun TodoItemInlineEditor(
    item: TodoItem,
    onEditItemChange: (TodoItem) -> Unit,
    onEditDone: () -> Unit,
    onRemoveItem: () -> Unit
) {
    TodoItemInput(
        text = item.task,
        onTextChange = {
            onEditItemChange(item.copy(task = it))
        },
        icon = item.icon,
        onIconChange = {
            onEditItemChange(item.copy(icon = it))
        },
        submit = onEditDone,
        iconsVisible = true
    ) {
        // 保存和删除两个图标
        Row {
            val shrinkButtons = Modifier.widthIn(20.dp)

            TextButton(onClick = onEditDone, modifier = shrinkButtons) {
                Text(
                    text = "\uD83D\uDCBE",// Emoji符号，软盘
                    textAlign = TextAlign.End,
                )
            }

            TextButton(onClick = onRemoveItem, modifier = shrinkButtons) {
                Text(
                    text = "✖",// Emoji符号，软盘
                    textAlign = TextAlign.End,
                )
            }
        }
    }
}


// 顶部输入框加上一个灰色背景
@Composable
fun TodoItemInputBackground(
    elevate: Boolean,
    modifier: Modifier = Modifier,
    content: @Composable RowScope.() -> Unit
) {
    // 帧动画的形式展现Surface底部的阴影
    val animatedElevation by animateDpAsState(
        targetValue = if (elevate) 1.dp else 0.dp,
        TweenSpec(durationMillis = 500), label = ""
    )

    Surface(
        color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.05f),
        shadowElevation = animatedElevation,
        shape = RectangleShape
    ) {
        Row(
            modifier = modifier.animateContentSize(animationSpec = TweenSpec(durationMillis = 500)),
            content = content
        )
    }
}

// 输入框
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun TodoInputText(
    text: String,
    onTextChange: (String) -> Unit,
    modifier: Modifier = Modifier,
    onItemAction: () -> Unit = {}
) {

    val keyboardController = LocalSoftwareKeyboardController.current

    TextField(
        value = text,
        onValueChange = onTextChange,
        colors = TextFieldDefaults.colors(
            focusedContainerColor = Color.Transparent, // 输入框获取焦点时候的容器颜色
            unfocusedContainerColor = Color.Transparent, // 输入框时区焦点时候的容器颜色
        ),
        maxLines = 1,
        modifier = modifier,
        keyboardOptions = KeyboardOptions.Default.copy(imeAction = ImeAction.Done),
        keyboardActions = KeyboardActions(onDone = {
            onItemAction()
            keyboardController?.hide()
        })
    )
}

// 按钮
@Composable
fun TodoEditButton(
    onClick: () -> Unit,
    text: String,
    modifier: Modifier = Modifier,
    enabled: Boolean = true
) {
    TextButton(
        onClick = onClick,
        shape = CircleShape,
        colors = ButtonDefaults.buttonColors(),
        modifier = modifier,
        enabled = enabled
    ) {
        Text(text = text)
    }
}

/**
 * 一排图标，根据文本框是否有内容，自动收起和弹出，带动画效果
 *
 * https://www.bilibili.com/video/BV1ob4y1a7ad/?p=36&spm_id_from=pageDriver&vd_source=e07cc8cc94eb22bd76722071b03cd199
 */
@Composable
fun AnimatedIconRow(
    icon: TodoIcon,
    onIconChange: (TodoIcon) -> Unit,
    modifier: Modifier = Modifier,
    visible: Boolean = true
) {

    val enter = remember {
        fadeIn(animationSpec = TweenSpec(300, easing = FastOutLinearInEasing))
    }

    val exit = remember {
        fadeOut(animationSpec = TweenSpec(100, easing = FastOutSlowInEasing))
    }

    Box(modifier = modifier.defaultMinSize(minHeight = 16.dp)) {
        AnimatedVisibility(visible = visible, enter = enter, exit = exit) {
            IconRow(icon = icon, onIconChange = onIconChange)
        }
    }
}

@Composable
fun IconRow(
    icon: TodoIcon,
    onIconChange: (TodoIcon) -> Unit,
    modifier: Modifier = Modifier
) {
    Row(modifier = modifier) {
        for (todoIcon in TodoIcon.values()) {
            SelectableIconButton(
                icon = todoIcon.imageVector,
                iconContentDescription = todoIcon.contentDescription,
                onIconSelected = { onIconChange(todoIcon) },
                isSelected = todoIcon == icon
            )
        }
    }
}

@Composable
fun SelectableIconButton(
    icon: ImageVector,
    iconContentDescription: Int,
    onIconSelected: () -> Unit,
    isSelected: Boolean,
    modifier: Modifier = Modifier
) {

    // 图标选中和未选中状态，颜色不一样
    val tint = if (isSelected) {
        MaterialTheme.colorScheme.primary
    } else {
        MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
    }

    TextButton(
        onClick = { onIconSelected() },
        shape = CircleShape,
        modifier = modifier
    ) {
        Column {
            Icon(
                imageVector = icon,
                tint = tint,
                contentDescription = stringResource(id = iconContentDescription)
            )

            if (isSelected) {
                Box(
                    modifier = Modifier
                        .padding(top = 3.dp)
                        .width(icon.defaultWidth)
                        .height(1.dp)
                        .background(tint)
                )
            } else {
                Spacer(modifier = Modifier.height(4.dp))
            }
        }
    }
}

@Composable
fun TodoItemEntryInput(onItemComplete: (TodoItem) -> Unit) {
    val (text, setText) = remember {
        mutableStateOf("")
    }
    val (icon, setIcon) = remember {
        mutableStateOf(TodoIcon.DEFAULT)
    }
    val iconsVisible = text.isNotBlank()

    // 点击"Add"按钮，提交要做的事情
    val submit = {
        onItemComplete(
            TodoItem(
                task = text,
                icon = icon,
            )
        )

        setIcon(TodoIcon.DEFAULT)

        setText("")

    }

    TodoItemInput(
        text = text,
        onTextChange = setText,
        icon = icon,
        onIconChange = setIcon,
        submit = submit,
        iconsVisible = iconsVisible,
        buttonSlot = {
            TodoEditButton(
                onClick = submit, text = "Add",
                modifier = Modifier.align(Alignment.CenterVertically),
                enabled = text.isNotBlank()
            )
        }
    )
}

@Composable
fun TodoItemInput(
    text: String,
    onTextChange: (String) -> Unit,
    icon: TodoIcon,
    onIconChange: (TodoIcon) -> Unit,
    submit: () -> Unit,
    iconsVisible: Boolean,
    // 最右侧的图标与按钮，在编辑时，会有删除和保存两个图标，添加时会有一个"Add”按钮
    buttonSlot: @Composable RowScope.() -> Unit
) {
    /**
     * 这个函数使用remember给自己添加内存，然后在内存中存储一个由 mutableStateOf 创建的MutableState<String>
     * 它是Compose 的内置类型，提供了一个 可观察的状态持有者。
     * val (value, setValue) = remember { mutableStateOf (default) }
     * 对value的任何更改都将自动重新组合读取此状态的任何可组合函数。
     *
     */

//    val (text, setText) = remember {
//        mutableStateOf("")
//    }
//    val (icon, setIcon) = remember {
//        mutableStateOf(TodoIcon.DEFAULT)
//    }
//    val iconsVisible = text.isNotBlank()
//
//    // 点击"Add"按钮，提交要做的事情
//    val submit = {
//        onItemComplete(
//            TodoItem(
//                task = text,
//                icon = TodoIcon.Trash,
//            )
//        )
//
//        setIcon(TodoIcon.DEFAULT)
//
//        setText("")
//
//    }

    Column {
        Row(
            modifier = Modifier
                .padding(horizontal = 16.dp)
                .padding(top = 16.dp)
        ) {

            // 输入框
            TodoInputText(
                text = text,
                onTextChange = onTextChange,
                modifier = Modifier
                    .weight(1f)
                    .padding(end = 8.dp),
                onItemAction = submit
            )
            // 按钮
            /*TodoEditButton(
                onClick = submit, text = "Add",
                modifier = Modifier.align(Alignment.CenterVertically),
                enabled = text.isNotBlank()
            )*/

            Spacer(modifier = Modifier.width(8.dp))

            Box(modifier = Modifier.align(Alignment.CenterVertically)) {
                this@Row.buttonSlot()
            }

        }

        if (iconsVisible) {
            AnimatedIconRow(
                icon = icon,
                onIconChange = onIconChange,
                modifier = Modifier.padding(top = 8.dp),
                visible = true
            )
        } else {
            Spacer(modifier = Modifier.height(16.dp))
        }
    }

}
